package com.github.baichuan.application.scaffold.rest.controller;

import com.github.baichuan.application.scaffold.rest.domain.application.Application;
import com.github.baichuan.application.scaffold.rest.domain.application.ApplicationService;
import com.github.baichuan.application.scaffold.rest.domain.identity.ApplicationMember;
import com.github.baichuan.application.scaffold.rest.domain.identity.ApplicationMemberService;
import com.github.baichuan.application.scaffold.rest.dto.membership.*;
import com.github.baichuan.application.scaffold.rest.jpa.identity.ApplicationMemberSpecification;
import com.github.baichuan.application.scaffold.rest.jpa.identity.MemberLoginSpecification;
import com.github.baichuan.application.scaffold.rest.dto.membership.*;
import com.github.baichuan.web.dto.Pagination;
import com.github.baichuan.web.dto.PaginationCriteria;
import com.github.baichuan.web.dto.Result;
import com.github.baichuan.web.security.Authorization;
import com.github.baichuan.web.servlet.Restful;
import com.github.baichuan.mapping.BeanMapper;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.stream.Collectors;

@Tag(name = "应用账号")
@RestController
@RequestMapping("/member")
public class MemberController {
    @Autowired
    public MemberController(ApplicationService applicationService,
                            ApplicationMemberService memberService) {
        this.applicationService = applicationService;
        this.memberService = memberService;
    }

    private ApplicationService applicationService;
    private ApplicationMemberService memberService;

    @Operation(summary = "查询")
    @PostMapping("/query")
    @Authorization("member:query")
    public ResponseEntity<Pagination<ApplicationMemberGridView>> query(@RequestHeader("x-application-code") @Parameter(hidden = true) String application,
                                                                       @RequestHeader("x-member-uid") String memberUid,
                                                                       @RequestBody @Validated PaginationCriteria<ApplicationMemberQueryCriteria> paginationCriteria)
            throws NoSuchFieldException {
        Application app = applicationService.findByCode(application);
        ApplicationMember applicationMember = memberService.find(application, memberUid);
        ApplicationMemberQueryCriteria criteria = paginationCriteria.getCriteria();
        ApplicationMemberSpecification specification = criteria.specification(app, applicationMember);

        Page<ApplicationMemberGridView> page = memberService.query(specification, paginationCriteria.pageable(ApplicationMemberGridView.class))
                .map(x -> BeanMapper.map(x, ApplicationMemberGridView.class));
        return ResponseEntity.ok(Pagination.of(page));
    }

//    @ApiOperation(summary="用户信息提示")
//    @GetMapping("/suggest/{keyword}")
//    public ResponseEntity suggest(@RequestHeader("x-application-code") @Parameter(hidden = true) String application, @PathVariable String keyword){
//        List<MemberSuggest> suggestInfos = memberService.suggest(application, keyword.trim())
//                .stream().map(x -> BeanMapper.map(x, MemberSuggest.class))
//                .collect(Collectors.toList());
//        return ResponseEntity.ok(suggestInfos);
//    }

    @GetMapping("/{id}")
    @Operation(summary = "表单数据")
    public ResponseEntity<EditForm> get(@RequestHeader("x-application-code") @Parameter(hidden = true) String application,
                                        @PathVariable("id") String id) {
        ApplicationMember member = memberService.find(application, id);
        EditForm form = BeanMapper.map(member, EditForm.class);
        form.setRoles(member.getRoles().stream().map(role -> role.getId()).collect(Collectors.toList()));
        return ResponseEntity.ok(form);
    }

    @PostMapping("/register")
    @Operation(summary = "注册")
    @Authorization("member:add")
    public ResponseEntity<Result> register(@RequestHeader("x-application-code") @Parameter(hidden = true) String application,
                                           @RequestBody @Valid RegisterForm form) {
        Result result = memberService.add(application, form);
        return Restful.created(result);
    }

    @Operation(summary = "修改")
    @PutMapping("/{id}")
    public ResponseEntity<Result> edit(@RequestHeader("x-application-code") @Parameter(hidden = true) String application,
                                       @PathVariable("id") String id, @RequestBody @Valid EditForm form) {
        Result result = memberService.edit(application, id, form);
        return Restful.response(result);
    }

    @Operation(summary = "删除")
    @DeleteMapping("/{uid}")
    @Authorization("member:remove")
    public ResponseEntity<Result> remove(@RequestHeader("x-application-code") @Parameter(hidden = true) String application,
                                         @PathVariable("uid") String uid) {
        Result result = memberService.remove(application, uid);
        return Restful.deleted(result);
    }

    @PutMapping("/password/reset")
    @Operation(summary = "重置密码")
    @Authorization("member:pwd-reset")
    public ResponseEntity<Result> resetPassword(@RequestHeader("x-application-code") @Parameter(hidden = true) String application,
                                                @RequestBody @Valid ResetPassword dto) {
        Result result = memberService.resetPassword(application, dto);
        return Restful.response(result);
    }

    @PostMapping("/password/change")
    @Operation(summary = "修改密码")
    public ResponseEntity<Result> changePassword(@RequestHeader("x-application-code") @Parameter(hidden = true) String application,
                                                 @RequestBody @Valid ChangePassword dto) {
        Result result = memberService.changePassword(application, dto);
        return ResponseEntity.ok(result);
    }

    @PostMapping("/{uid}/login")
    @Operation(summary = "用户登录日志")
    public ResponseEntity<Pagination<SigninGridView>> login(@RequestHeader("x-application-code") @Parameter(hidden = true) String application,
                                @RequestBody PaginationCriteria paginationCriteria,
                                @PathVariable("uid") String uid) {
        ApplicationMember applicationMember = memberService.find(application, uid);
        MemberLoginSpecification specification = new MemberLoginSpecification(applicationMember);
        Page<SigninGridView> viewPage = memberService.signinLogs(specification, paginationCriteria.pageable())
                .map(x -> BeanMapper.map(x, SigninGridView.class));
        return ResponseEntity.ok(Pagination.of(viewPage));
    }
}
